<script setup>
import {ref, onMounted, reactive} from "vue";
import {camelCaseToHumpBack, formatTreeNode, getEditorContentLength, resolveNodeTree, getLastChildNode} from "./utils";
import AeEditorToolsBar from "./components/AeEditorToolsBar.vue"

defineOptions({
  name: 'AeEditor'
})

const props = defineProps({
  value: {
    type: Array,
    default: () => ([])
  },

})
const AeEditorContent = ref(null)
const selectNode = ref({})
const timer =  ref(0)

const emit = defineEmits(['update:value', 'change', 'blur', 'focus', 'keyup', 'keydown', 'input'])

/**
 * changeEditor
 *
 * @Description: 监听编辑器change事件
 * @Params: e 事件对象
 * @CreateTime: 2023/7/6
 * @Author: Zeman
 *
 */
const changeEditor = (e) => {
  const treeNode = formatTreeNode(AeEditorContent.value)
  emit('update:value', treeNode)
  emit('change', {
    value: treeNode,
    editorEl: AeEditorContent,
    $event: e,
    length: getEditorContentLength(AeEditorContent)
  })
}

/**
 * blurEditor
 *
 * @Description: 监听编辑器blur事件
 * @Params: e 事件对象
 * @CreateTime: 2023/7/6
 * @Author: Zeman
 *
 */
const blurEditor = (e) => {
  emit('blur', {
    value: formatTreeNode(AeEditorContent.value),
    editorEl: AeEditorContent,
    $event: e,
    length: getEditorContentLength(AeEditorContent)
  })
}

/**
 * focusEditor
 *
 * @Description: 监听编辑器focus事件
 * @Params: e 事件对象
 * @CreateTime: 2023/7/6
 * @Author: Zeman
 *
 */
const focusEditor = (e) => {
  emit('focus', {
    value: formatTreeNode(AeEditorContent.value),
    editorEl: AeEditorContent,
    $event: e,
    length: getEditorContentLength(AeEditorContent)
  })
}

/**
 * keyupEditor
 *
 * @Description: 监听编辑器keyup事件
 * @Params: e 事件对象
 * @CreateTime: 2023/7/6
 * @Author: Zeman
 *
 */
const keyupEditor = (e) => {
  const treeNode = formatTreeNode(AeEditorContent.value)
  // console.log('formatTreeNode', formatTreeNode(AeEditorContent.value))
  // console.log('resolveTreeNode', resolveNodeTree(treeNode))
  emit('update:value', treeNode)
  emit('keyup', {
    value: formatTreeNode(AeEditorContent.value),
    editorEl: AeEditorContent,
    $event: e,
    length: getEditorContentLength(AeEditorContent)
  })
  const selection = window.getSelection(); // 获取选区对象
  const selectedText = selection.toString().trim(); // 获取选中的文字
  let obj = {}
  for (let k in selection) {
    obj[k] = selection[k]
  }
  selectNode.value = {...obj}
}

/**
 * keydownEditor
 *
 * @Description: 监听编辑器keydown事件
 * @Params: e 事件对象
 * @CreateTime: 2023/7/6
 * @Author: Zeman
 *
 */
const keydownEditor = (e) => {
  handleKeyDown(e)
  emit('keydown', {
    value: formatTreeNode(AeEditorContent.value),
    editorEl: AeEditorContent,
    $event: e,
    length: getEditorContentLength(AeEditorContent)
  })
}
const handleMouseUp = (e) => {
  const selection = window.getSelection(); // 获取选区对象
  const selectedText = selection.toString().trim(); // 获取选中的文字
  if (selectedText) {
    console.log(selection)
    const range = selection.getRangeAt(0); // 获取选中的范围
    const span = document.createElement('b'); // 创建 <a> 元素
    const parentElement = range.commonAncestorContainer; // 获取包含选中内容的最近的父节点
    // 检查父节点是否为文本节点，如果是则直接包裹，否则逐级向上寻找可包裹的节点
    if (parentElement.nodeType === Node.TEXT_NODE) {
      const aTag = createAnchorTag(selectedText); // 创建 <a> 元素
      range.surroundContents(aTag); // 包裹选中的内容
    } else {
      wrapNonTextNode(range, selectedText); // 包裹非文本节点的选中内容
    }
    span.textContent = selectedText; // 设置 <a> 元素的文本内容
    range.surroundContents(span);
    console.log(range)
    // 更新 Vue 的响应式变量 content
  }
  let obj = {}
  for (let k in selection) {
    obj[k] = selection[k]
  }
  selectNode.value = {...obj}

  console.log(selectNode.value, selection,123123)
}
// 创建 <a> 元素
const createAnchorTag = (text) => {
  const aTag = document.createElement('b');
  aTag.href = 'https://example.com';
  aTag.textContent = text;
  return aTag;
};

// 逐级向上包裹非文本节点的选中内容
const wrapNonTextNode = (range, text) => {
  let node = range.commonAncestorContainer;

  while (node && node.parentNode) {
    const parent = node.parentNode;
    const tempRange = range.cloneRange(); // 创建临时的 Range 对象
    tempRange.selectNodeContents(node);

    if (tempRange.toString().trim() === text) {
      const aTag = createAnchorTag(text); // 创建 <a> 元素
      tempRange.surroundContents(aTag); // 包裹选中的内容
      range.setStartBefore(node); // 设置新的范围的起始位置
      range.setEndAfter(node); // 设置新的范围的结束位置
      parent.replaceChild(aTag, node); // 替换父节点中的原始节点为 <a> 元素
      break;
    }

    node = parent;
  }
};

const handleInput = (e) => {

  emit('input', {
    value: formatTreeNode(AeEditorContent.value),
    editorEl: AeEditorContent,
    $event: e,
    length: getEditorContentLength(AeEditorContent)
  })
}
const handleKeyDown = (event) => {
  // 处理按键事件
  if (event.keyCode === 13) {

    // 检查光标是否在最后
    const selection = window.getSelection();
    const editor = AeEditorContent.value;

    if (selection.rangeCount > 0) {
      const range = selection.getRangeAt(0);
      if ((getLastChildNode(editor) || range.startContainer) === getLastChildNode(editor) && (range.startOffset === getLastChildNode(editor).length || !range.startOffset)) {
        let now = new Date().getTime()
        if (timer.value && now - timer.value < 240) {
          event.preventDefault();
          const p = document.createElement('p')
          p.setAttribute('style','width:100%;height:20px;')
          editor.appendChild(p);
          range.selectNodeContents(editor);
          range.collapse(false); // 将 Range 折叠到最后一个位置

          // 清除之前的选择范围
          selection.removeAllRanges();

          // 将新的 Range 对象添加到 Selection 对象中
          selection.addRange(range);
          timer.value = 0
        } else {
          timer.value = now
        }
      }
    }

  }
}
onMounted(() => {
  if (props.value.length) {
    try {
      const nodeTree = resolveNodeTree(props.value)
      if (nodeTree.length) {
        AeEditorContent.value.append(...nodeTree)
      }
    } catch (e) {
      console.error(e)
    }
  }
  console.log(getEditorContentLength(AeEditorContent))
  console.log(AeEditorContent)
  console.log(camelCaseToHumpBack('-webkit-tap-highlight-color'))
})

</script>

<template>
  <div class="ae-editor">
    <ae-editor-tools-bar :cursor="selectNode"></ae-editor-tools-bar>
    <div class="ae-editor-content" 
         contenteditable="true" 
         ref="AeEditorContent" 
         @keyup="keyupEditor" 
         @keydown="keydownEditor"
         @change="changeEditor"
         @blur="blurEditor"
         @focus="focusEditor"
         @mouseup.stop="handleMouseUp"
         @input="handleInput"
    >
    </div>
  </div>
</template>

<style scoped lang="scss">
.ae-editor {
  width: 600px;
  min-height: 400px;
  margin: auto;
  border: 1px solid #bdbdbd;
  border-radius: 5px;
  box-shadow: #bdbdbd 0 0 2px;
  .ae-editor-content {
    min-height: 400px;
    padding: 30px;
    &:focus {
      outline: none;
    }
  }
}
</style>